﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Threading;
using CoreClasses;
using LayoutPlanning.CollaborationService;
using Mvvm;
using Mvvm.UI;
using LayoutPlanning.Helpers;
using LayoutPlanning.Model;
using LayoutPlanning.Views;
using Microsoft.Win32;
using Mvvm.Native;
using Mvvm.Services.FileDialogServices;
using Mvvm.UI.Services;
using Rectangle = System.Drawing.Rectangle;

namespace LayoutPlanning.ViewModel
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class Layouts : ViewModelBase
    {
        private ObservableCollection<LayoutModel> _layoutList = new ObservableCollection<LayoutModel>();
        private ProjectViewModel[] _projectsInLayout;
        private ProjectViewModel _selectedProject;
        private LayoutModel _selectLayout;

        /// <summary>
        /// Initializes a new instance of the Layouts class.
        /// </summary>
        public Layouts()
        {
            UpdateLayout();
            

        }

        private void UpdateLayout()
        {
#if DEBUG
            var service = new CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContractDebug");
#else
            var service = new CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContract");
#endif
            var lay = service.GetLayouts();
            
            LayoutList.Clear();
            foreach (var layout in lay)
            {
                
                LayoutList.Add(new LayoutModel()
                {
                    Layout = layout.LayoutElement?.GetObject(),
                    LayoutName = layout.LayoutName,
                    Pointcloud = layout.PointCloudReference,
                    Height = layout.Height,
                    Width = layout.Width
                });
            }
            
            SelectedProject = null;
            SelectLayout = LayoutList.FirstOrDefault();
            ViewModelLocator.Stations.Reset();
            
        }


        public ObservableCollection<LayoutModel> LayoutList
        {
            get { return _layoutList; }
            set
            {
                _layoutList = value;
                RaisePropertyChanged();
            }
        }

        public LayoutModel SelectLayout
        {
            get { return _selectLayout; }
            set
            {
                _selectLayout = value;
                RaisePropertyChanged();
                
                ViewModelLocator.Main.Layout = value;
                Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action( async ()=>
                {
                    var t = UpdateProjects(value?.LayoutName);
                   //ViewModelLocator.Main.NormalizeZoom.Execute(null);
                    await t;
                }));
            }
        }

     

        public async Task UpdateProjects(string t)
        {
#if DEBUG
            var service = new CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContractDebug");
#else
                    var service = new  CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContract");
#endif
            ProjectsInLayout = (await service.GetProjectAreasAsync(t)).Select(tt=>new ProjectViewModel(tt)).ToArray();
        }

        public ProjectViewModel[] ProjectsInLayout
        {
            get { return _projectsInLayout; }
            set
            {
                if(ReferenceEquals(value, _projectsInLayout))
                    return;
                _projectsInLayout = value;
                RaisePropertyChanged();
                RaisePropertyChanged(nameof(ProjectsInLayoutExceptSelected));

            }
        }
        public RelayCommand<LayoutModel> DeleteLayout => new RelayCommand<LayoutModel>((t) =>
        {
#if DEBUG
            var service = new CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContractDebug");
#else
            var service = new CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContract");
#endif
            service.DeleteLayout(t.LayoutName);
            foreach (var projectViewModel in ProjectsInLayout)
            {
                service.DeleteProject(projectViewModel.Name, t.LayoutName);
            }
            UpdateLayout();
           

        });
        public IEnumerable<ProjectViewModel> ProjectsInLayoutExceptSelected => SelectedProject == null ? ProjectsInLayout:ProjectsInLayout.Except(new []{SelectedProject});
        public ProjectViewModel SelectedProject

        {
            get { return _selectedProject; }
            set
            {
                if(_selectedProject == value)
                    return;
                _selectedProject = value;
                RaisePropertyChanged();
                ViewModelLocator.Main.LoadProject(_selectedProject?.Project);
                RaisePropertyChanged(nameof(ProjectsInLayoutExceptSelected));
                
            }
        }

        public RelayCommand<ProjectArea> DeleteProject => new RelayCommand<ProjectArea>(async t =>
        {
#if DEBUG
            var service = new CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContractDebug");
#else
                    var service = new  CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContract");
#endif
            service.DeleteProject(t.ProjectAreaName, ViewModelLocator.Main.Layout.LayoutName);
           await UpdateProjects(ViewModelLocator.Main.Layout.LayoutName);

        }); 
        
       

        public RelayCommand CreateNewEmpty
        {
            get { return new RelayCommand(()=> LayoutList.Add(new LayoutModel() {Height = 10000, Width = 10000}));}
        }
        public RelayCommand ImportNewLayout
        {
            get
            {
                return new RelayCommand(async () =>
                {
                    await ViewModelLocator.Dispatcher.InvokeAsync(() =>
                    {
                        var dialog = new OpenFileDialogService();
                        if (dialog.ShowDialog())
                        {
                            var shapes = DFXImporter.LoadDxf(dialog.GetFullFileName(), 1000);
                            double minLeft = shapes.OfType<Line>().Min(i => Math.Min(i.X1, i.X2));
                            double maxLeft = shapes.OfType<Line>().Max(i => Math.Max(i.X1, i.X2));
                            double minTop = shapes.OfType<Line>().Min(i => Math.Min(i.Y1, i.Y2));
                            double maxTop = shapes.OfType<Line>().Max(i => Math.Max(i.Y1, i.Y2));
                            var canvas = new Canvas()
                            {
                                VerticalAlignment = VerticalAlignment.Stretch,
                                HorizontalAlignment = HorizontalAlignment.Stretch
                            };


                            foreach (var shape  in shapes)
                            {
                                canvas.Children.Add(shape);
                            }
                            canvas.Width = maxLeft - minLeft;
                            canvas.Height = maxTop - minTop;
                            var layoutmodel = new LayoutModel();
                            layoutmodel.Layout = new SerializableFrameworkElement(new ContentControl() { Content = canvas});
                            layoutmodel.LayoutName = "New Layout";
                            LayoutList.Add(layoutmodel);

                            canvas.UpdateLayout();
                        }
                    });
                });
            }
        }


        public async Task AddNewProject(string layoutName, Rectangle rectangle)
        {
#if DEBUG
            var service = new CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContractDebug");
#else
                    var service = new  CollaborationService.ServiceContractClient("BasicHttpsBinding_IServiceContract");
#endif
            var name = "New Project";
            var number = 0;
            while (
                ProjectsInLayout.FirstOrDefault(
                    t => (name +" " + (number == 0 ? "" : number.ToString())).Equals(t.Project.ProjectAreaName)) != null)
                number++;


            await service.AddProjectAreaAsync(layoutName, name +" "+ (number == 0 ? "" : number.ToString()), rectangle, null);

            await UpdateProjects(layoutName);

            SelectedProject = ProjectsInLayout.FirstOrDefault(t => t.Project.ProjectAreaName == name + " " + (number == 0 ? "" : number.ToString()));
        }
    }
}